/*!
 * @file
 * @brief SPI控制相关方法（包括模拟SPI和外设SPI）
 */

#pragma once

/*-----------------------------------------------------------------------------
 * HEADER FILES
 *---------------------------------------------------------------------------*/
#include <stdbool.h>
#include <stdint.h>

#include "gmi_device.h"
#include "gmi_gpio.h"
#include "gmi_status.h"

/*-----------------------------------------------------------------------------
 * TYPE DEFINITION
 *---------------------------------------------------------------------------*/
typedef pvoid gmi_spi_device_handle_t;  // 用于各个平台的SPI外设句柄

/*-----------------------------------------------------------------------------
 * ENUM
 *---------------------------------------------------------------------------*/
/**
 * @brief 通信模式
 */
enum gmi_spi_master_mode_e
{
    GMI_SPI_MASTER_MODE_DISABLE = 0,  ///< 从设备模式
    GMI_SPI_MASTER_MODE_ENABLE        ///< 主设备模式
};

/**
 * @brief 传输模式
 */
enum gmi_spi_transmission_mode_e
{
    GMI_SPI_SIMPLEX = 0,  ///< 单工
    GMI_SPI_HALF_DUPLEX,  ///< 半双工
    GMI_SPI_FULL_DUPLEX   ///< 全双工
};

/**
 * @brief CPOL
 */
enum gmi_spi_cpol_e
{
    GMI_SPI_CPOL_LOW = 0,  ///< CPOL为0
    GMI_SPI_CPOL_HIGH      ///< CPOL为1
};

/**
 * @brief CPHA
 */
enum gmi_spi_cpha_e
{
    GMI_SPI_CPHA_1ST_EDGE = 0,  ///< CPHA=0
    GMI_SPI_CPHA_2ND_EDGE       ///< CPHA=1
};

/**
 * @brief 大小端设置
 */
enum gmi_spi_first_bit_e
{
    GMI_SPI_FIRSTBIT_LSB = 0,  ///< 小端
    GMI_SPI_FIRSTBIT_MSB       ///< 大端
};

/*-----------------------------------------------------------------------------
 * DATA STRUCTURE
 *---------------------------------------------------------------------------*/

/**
 * @brief SPI设备配置
 */
typedef struct gmi_spi_st
{
    gmi_device_handle_t type;        ///< 外设类型
    gmi_spi_device_handle_t handle;  ///< 用于各平台SPI外设的句柄
    gmi_gpio_t mosi;                 ///< mosi引脚
    gmi_gpio_t miso;                 ///< miso引脚
    gmi_gpio_t sclk;                 ///< sclk引脚
    gmi_gpio_t ncs;                  ///< ncs引脚
    enum gmi_spi_cpol_e cpol;        ///< CPOL
    enum gmi_spi_cpha_e cpha;        ///< CPHA
    bool cs_enable;                  ///< CS使能
    bool crc_enable;                 ///< CRC使能
    uint32_t clock_speed;            ///< 时钟速率
    enum gmi_spi_master_mode_e master_mode;       ///< 通信模式
    enum gmi_spi_transmission_mode_e trans_mode;  ///< 传输模式
} GMI_SPI;

/**
 * @brief GPIO模拟SPI设备配置
 */
typedef struct gmi_gpio_simulated_spi_st
{
    gmi_gpio_t sdio;
    gmi_gpio_t sclk;
    gmi_gpio_t ncs;
    int delay_slices;
    enum gmi_spi_cpol_e cpol;  ///< CPOL
    enum gmi_spi_cpha_e cpha;  ///< CPHA
} gmi_gpio_simulated_spi_t;

/*-----------------------------------------------------------------------------
 * FUNCTIONS DECLARATION
 *---------------------------------------------------------------------------*/

/**
 * @brief 提供SPI设备初始化功能
 * @param {GMI_SPI_CONFIG} *spi_config
 * @return 非零则异常
 * @note 需要提前声明 GMI_SPI 类型变量，使用地址传递参数
 */
GMI_STATUS
gmi_spi_init(GMI_SPI* spi);

/**
 * @brief 销毁spi设备
 * @param {GMI_SPI} *spi
 * @return 非零则异常
 */
GMI_STATUS gmi_spi_deinit(GMI_SPI* spi);

/**
 * @brief spi传输数据
 * @param {GMI_SPI} *spi
 * @param {uint8_t*} data_buffer
 * @param {uint32_t} size
 * @return 非零则异常
 */
GMI_STATUS gmi_spi_transmit(GMI_SPI* spi, uint8_t* data_buffer, size_t size);

/**
 * @brief SPI接收数据
 * @param {GMI_SPI} *spi
 * @param {uint8_t*} data_buffer
 * @param {uint32_t} size
 * @return 非零则异常
 */
GMI_STATUS gmi_spi_receive(GMI_SPI* spi, uint8_t* data_buffer, size_t size);
